<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es5 显示原型中的属性</title>
  <!-- 
  在 JavaScript ES5 中，原型（prototype）是一个非常重要的概念，它允许我们在构造函数中定义方法和属性，从而使得所有实例可以共享这些方法和属性。
  1. 原型的基本概念
  - 每个 JavaScript 对象都有一个内部属性  `[[Prototype]]` ，指向另一个对象，这个对象被称为原型。
  - 原型可以用  `Object.getPrototypeOf(obj)`  或者  `obj.__proto__`  来访问。

  2. 构造函数与原型
  - 当你定义一个构造函数时，可以在其  `prototype`  属性上添加方法和属性，这样所有通过该构造函数创建的实例都可以访问这些方法和属性。
  function Person(name) {
      this.name = name;
  }

  Person.prototype.sayHello = function() {
      console.log("Hello, " + this.name);
  };

  var alice = new Person("Alice");
  alice.sayHello(); // 输出: Hello, Alice
  3. 原型链
  - 当访问一个对象的属性或方法时，JavaScript 引擎会首先查找对象本身，如果没有找到，就会查找它的原型，直到找到属性或达到原型链的末尾（通常是  `null` ）。
  - 这就是所谓的原型链（prototype chain）。

  4. 原型属性的共享
  - 原型上的属性是共享的，这意味着如果你在原型上定义一个属性，所有实例都将共享这个属性。
  Person.prototype.species = "Homo sapiens";

  console.log(alice.species); // 输出: Homo sapiens
  5. 修改原型
  - 可以在任何时候修改原型，新增或删除属性和方法，这会影响到所有实例。
  Person.prototype.sayGoodbye = function() {
      console.log("Goodbye, " + this.name);
  };

  alice.sayGoodbye(); // 输出: Goodbye, Alice
  6. 注意事项
  - 如果实例对象有与原型同名的属性，实例对象会优先使用自己的属性，这被称为“遮蔽”（shadowing）。
  - 使用  `Object.create(proto)`  可以创建一个新对象，并将其原型设置为  `proto` 。

  总结
  原型是 JavaScript 中实现继承和代码重用的核心机制。理解原型和原型链对于深入掌握 JavaScript 的对象模型至关重要。通过合理使用原型，可以有效地管理内存和提高代码的可维护性。
  -->
</head>
<body>

  <script>
    // 1. 原型对象
    // 非常重要的属性: constructor, 指向Person函数对象
    function Person(name) {
      this.name = name;
    }

    const PersonPrototype = Person.prototype;
    console.log(PersonPrototype);
    console.log(PersonPrototype.constructor === Person); // 输出: true
    console.log(PersonPrototype.constructor.name, Person.name);
    
    // 2.实例对象
    const p = new Person('Alice');
    console.log(p.__proto__.constructor);
    console.log(p.__proto__.constructor.name, Person.name);

  </script>
  
</body>
</html>